import cv2
import numpy as np
from skimage import transform


class Revolver(object):
    """
    按一定角度旋转图像并切割为子图
    """

    def __init__(self, image_path, revolve_angle=30, params=None):
        """
        初始化

        Parameters
        ----------
        image_path
        revolve_angle
        params
        """
        self._image = cv2.imread(image_path) if isinstance(image_path, str) else image_path
        self._image_size = self._image.shape
        self._revolve_angle = revolve_angle
        self._params = params

        # 切割位置
        try:
            self._crop_params = self._params['crop']
        except KeyError:
            self._crop_params = {'edge': {'seat': ((50, 480), (170, 480)), 'size': (320, 320)},
                                 'center': {'seat': ((440, 440),), 'size': (400, 400)}}

        self._revolved_image_size = None
        self._revolved_image = None
        self._angle = 0
        self._output = {}
        self._info = {}

    @property
    def params(self):
        return self._params

    @property
    def info(self):
        return self._info

    @property
    def angle(self):
        return self._angle

    @property
    def image_size(self):
        return self._image_size

    @property
    def output(self):
        return self._output

    @property
    def revolved_image_size(self):
        return self._revolved_image_size

    def _get_revolved_size(self):
        """
        计算旋转后的图像大小
        """
        angle = self._angle * np.pi / 180
        self._revolved_image_size = list(self._image_size)
        self._revolved_image_size[0] = \
            np.ceil(abs(self._image_size[0] * np.cos(angle)) +
                    abs(self._image_size[1] * np.sin(angle))).astype(np.int32)
        self._revolved_image_size[1] = \
            np.ceil(abs(self._image_size[1] * np.cos(angle)) +
                    abs(self._image_size[0] * np.sin(angle))).astype(np.int32)

    def _revolve_image(self):
        """
        使用scikit-image包的函数进行旋转

        Returns
        -------

        """
        self._revolved_image = transform.rotate(self._image, self._angle, resize=True, preserve_range=True)
        self._revolved_image = self._revolved_image.round().astype(np.int32)
        d = list(map(lambda x, y: (x - y) // 2, self._revolved_image_size, self._image_size))
        h, w, _ = self._image_size
        self._revolved_image = self._revolved_image[d[0]:(d[0] + h), d[1]:(d[1] + w), :]

    def _crop_process(self):
        """
        自定义的切割方案

        Returns
        -------

        """
        pass

    def _crop_image(self):
        """
        按照定义的切割位置执行切割方案

        Returns
        -------

        """
        self._output[self._angle] = {}
        for key, value in self._crop_params.items():
            h, w = value['size']
            self._output[self._angle][key] = {}
            for s in value['seat']:
                self._info.clear()
                self._info['other'] = {'seat': s, 'size': (h, w)}
                self._info['image'] = self._revolved_image[s[0]:(s[0] + h), s[1]:(s[1] + w), :]
                self._crop_process()
                _key = '{}_{}_{}_{}'.format(key, self._angle, *s)
                self._output[self._angle][key][_key] = self._info.copy()

    def _process_angle(self):
        """
        可能处理角度的方法

        Returns
        -------

        """
        pass

    def _traverse_angles(self):
        """
        按照给定的角度依次旋转图像

        Returns
        -------

        """
        angles = list(range(0, 360, self._revolve_angle))
        for angle in angles:
            self._angle = angle
            self._get_revolved_size()
            self._process_angle()
            self._revolve_image()
            self._crop_image()

    def update(self):
        """
        运行全部

        Returns
        -------

        """
        self._traverse_angles()

